package com.wangjiacai.hqlQuery.configuration;

import com.wangjiacai.hqlQuery.properties.HibernateProperties;
import com.wangjiacai.hqlQuery.properties.HikariConfigProperties;
import com.wangjiacai.hqlQuery.repository.BaseRepository;
import com.wangjiacai.hqlQuery.repository.impl.HibernateBaseRepositoryImpl;
import com.zaxxer.hikari.HikariDataSource;
import org.hibernate.SessionFactory;
import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties;
import org.springframework.boot.autoconfigure.orm.jpa.JpaProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.orm.hibernate5.HibernateTransactionManager;
import org.springframework.orm.hibernate5.LocalSessionFactoryBean;
import org.springframework.orm.jpa.JpaVendorAdapter;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.orm.jpa.vendor.AbstractJpaVendorAdapter;
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;

import javax.sql.DataSource;
import java.util.Properties;

/*
 * @auther: wangjiacai
 *
 * @create: 2019-01-27 14:47:17
 */
@Configuration
@EnableConfigurationProperties({ HibernateProperties.class, DataSourceProperties.class,JpaProperties.class, HikariConfigProperties.class})
public class HibernateHqlQueryConfiguration {

    @Bean
    public BaseRepository baseRepository(){
        return new HibernateBaseRepositoryImpl();
    }

    @Bean
    public DataSource dataSource(DataSourceProperties properties,HikariConfigProperties hikariConfig){
        HikariDataSource dataSource = properties.initializeDataSourceBuilder().type(HikariDataSource.class).build();
        hikariConfig.setJdbcUrl(properties.getUrl());
        hikariConfig.setDriverClassName(properties.getDriverClassName());
        hikariConfig.setUsername(properties.getUsername());
        hikariConfig.setPassword(properties.getPassword());
        hikariConfig.validate();
        hikariConfig.copyStateTo(dataSource);
        return dataSource;
    }

    @Bean
    public LocalSessionFactoryBean sessionFactory(DataSource dataSource, HibernateProperties hibernateProperties) {
        LocalSessionFactoryBean factoryBean=new LocalSessionFactoryBean();
        factoryBean.setDataSource(dataSource);
        if(hibernateProperties.getPackagesToScan()!=null)  factoryBean.setPackagesToScan(hibernateProperties.getPackagesToScan());
        Properties properties=new Properties();
        properties.setProperty("hibernate.dialect",hibernateProperties.getDialect());
        properties.setProperty("hibernate.show_sql",hibernateProperties.getShow_sql());
        properties.setProperty("hibernate.format_sql",hibernateProperties.getFormat_sql());
        properties.setProperty("hibernate.hbm2ddl.auto",hibernateProperties.getHbm2ddl());
        factoryBean.setHibernateProperties(properties);
        return factoryBean;
    }

    @Bean
    public HibernateTransactionManager transactionManager(SessionFactory sessionFactory){
        return new HibernateTransactionManager(sessionFactory);
    }

    @Bean
    public JpaVendorAdapter jpaVendorAdapter(JpaProperties jpaProperties,DataSource dataSource) {
        AbstractJpaVendorAdapter adapter = new HibernateJpaVendorAdapter();
        adapter.setShowSql(jpaProperties.isShowSql());
        adapter.setDatabase(jpaProperties.determineDatabase(dataSource));
        adapter.setDatabasePlatform(jpaProperties.getDatabasePlatform());
        adapter.setGenerateDdl(jpaProperties.isGenerateDdl());
        return adapter;
    }

    @Bean
    @Primary
    public LocalContainerEntityManagerFactoryBean entityManagerFactory(HibernateProperties hibernateProperties,JpaVendorAdapter jpaVendorAdapter,DataSource dataSource){
        LocalContainerEntityManagerFactoryBean entityManagerFactoryBean= new LocalContainerEntityManagerFactoryBean();
        entityManagerFactoryBean.setDataSource(dataSource);
        if(hibernateProperties.getPackagesToScan()!=null) entityManagerFactoryBean.setPackagesToScan(hibernateProperties.getPackagesToScan());
        entityManagerFactoryBean.setJpaVendorAdapter(jpaVendorAdapter);
        return entityManagerFactoryBean;
    }
    public static void main(String[] args) {

    }
}
